package com.estun.backroundManagementService.modules.workOrder.service.Impl;// WorkOrderServiceImpl.java


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.estun.backroundManagementService.config.factoryMes.ApiCaller;
import com.estun.backroundManagementService.config.properties.ApiInfoProperties;
import com.estun.backroundManagementService.domain.BaseResponse;
import com.estun.backroundManagementService.domain.factoryMes.FactoryMesResponse;
import com.estun.backroundManagementService.domain.factoryMes.request.AlterScheduleStatusRequest;
import com.estun.backroundManagementService.domain.factoryMes.request.base.BaseMesRequest;
import com.estun.backroundManagementService.domain.factoryMes.request.base.BaseMesResponse;
import com.estun.backroundManagementService.enums.WorkOrderStatusEnum;
import com.estun.backroundManagementService.modules.material.mapper.MaterialMapper;
import com.estun.backroundManagementService.modules.material.model.Material;
import com.estun.backroundManagementService.modules.workOrder.dto.WorkOrderEntity;
import com.estun.backroundManagementService.modules.workOrder.mapper.WorkOrderMapper;
import com.estun.backroundManagementService.modules.workOrder.service.WorkOrderService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrderEntity> implements WorkOrderService {


    private final ApiCaller apiCaller;

    private final ApiInfoProperties apiInfoProperties;

    private final MaterialMapper materialMapper;

    @Override
    @Transactional
    public FactoryMesResponse push(BaseMesRequest<WorkOrderEntity> request) {
        List<WorkOrderEntity> list = request.getData();
        boolean save = false;
        try {
            for (WorkOrderEntity workOrderEntity : list) {
                String materialCode = workOrderEntity.getMaterialCode();

                List<Material> materialList = materialMapper.selectList(new QueryWrapper<Material>().eq("material_code", materialCode));
                Material material = materialList.get(0);
                if (!"成品".equals(material.getMaterialType())) {
                    workOrderEntity.setScheduleType(2);
                } else {
                    workOrderEntity.setScheduleType(1);
                }
                String scheduleCode = workOrderEntity.getScheduleCode();
                if (getByScheduleCode(scheduleCode) != null) {
                    save = update(workOrderEntity, new QueryWrapper<WorkOrderEntity>().eq("schedule_code", scheduleCode));
                } else {
                    save = save(workOrderEntity);
                }
            }
            if (save) {
                return FactoryMesResponse.success();
            } else {
                return FactoryMesResponse.error("保存失败");
            }
        } catch (Exception e) {
            log.error("【工单推送】 保存失败:{}", e.getMessage());
            return FactoryMesResponse.error(e.getMessage());
        }
    }

    /**
     * 完成排程
     */


    /**
     * 更新工单状态
     */
    @Override
    public BaseResponse updateScheduleStatus(WorkOrderEntity workOrder, WorkOrderStatusEnum statusEnum) {
        //如果目标排程状态未 3进行中 需要检查当前是否有其它排程未进行中
        String scheduleStatusCode = statusEnum.getCode();
        if (WorkOrderStatusEnum.IN_PRODUCTION.getCode().equals(scheduleStatusCode)) {
            List<WorkOrderEntity> inProductionList = list(new QueryWrapper<WorkOrderEntity>().eq("schedule_status", scheduleStatusCode));
            if (CollectionUtils.isNotEmpty(inProductionList)) {
                String collect = inProductionList.stream().map(WorkOrderEntity::getScheduleCode).collect(Collectors.joining(","));
                return BaseResponse.error("当前(" + collect + ")排程未完成，请完成或修改后再试");
            }
        }
        BaseMesRequest<AlterScheduleStatusRequest> mesRequest = getAlterScheduleStatusRequestBaseMesRequest(workOrder, scheduleStatusCode);
        BaseMesResponse post = apiCaller.post(apiInfoProperties.getAlterScheduleStatus(), mesRequest, BaseMesResponse.class);
        if (post.isSuccess()) {
            //同步更新工厂mes支线排程状态
            WorkOrderEntity xpcScheduleByMain = getXpcScheduleByMain(workOrder.getScheduleCode());
            BaseMesRequest<AlterScheduleStatusRequest> xpcMesRequest = getAlterScheduleStatusRequestBaseMesRequest(xpcScheduleByMain, scheduleStatusCode);
            BaseMesResponse xpcPost = apiCaller.post(apiInfoProperties.getAlterScheduleStatus(), xpcMesRequest, BaseMesResponse.class);
            if (!xpcPost.isSuccess()) {
                log.error("【排程状态更新】,支线排程跟新失败:{}", JSONUtil.toJsonStr(xpcMesRequest));
            }
            WorkOrderEntity toBeUpdate = new WorkOrderEntity();
            toBeUpdate.setId(workOrder.getId());
            toBeUpdate.setScheduleStatus(scheduleStatusCode);
            updateById(toBeUpdate);

            //同步更新产线mes支线排程状态
            WorkOrderEntity xpcToBeUpdate = new WorkOrderEntity();
            xpcToBeUpdate.setId(xpcScheduleByMain.getId());
            xpcToBeUpdate.setScheduleStatus(scheduleStatusCode);
            updateById(xpcToBeUpdate);
            return BaseResponse.success("更新成功");
        } else {
            log.error("状态更新失败,排程信息:{}，目标状态:{},工厂mes返回:{}", workOrder, statusEnum, post);
            return BaseResponse.error("更新失败,工厂mes返回:" + JSONUtil.toJsonStr(post));
        }
    }

    private static BaseMesRequest<AlterScheduleStatusRequest> getAlterScheduleStatusRequestBaseMesRequest(WorkOrderEntity workOrder, String scheduleStatusCode) {
        AlterScheduleStatusRequest alterScheduleStatusRequest = new AlterScheduleStatusRequest();
        alterScheduleStatusRequest.setScheduleCode(workOrder.getScheduleCode());
        alterScheduleStatusRequest.setOrderCode(workOrder.getOrderCode());
        alterScheduleStatusRequest.setScheduleStateCode(scheduleStatusCode);
        BaseMesRequest<AlterScheduleStatusRequest> mesRequest = new BaseMesRequest<>();
        mesRequest.setData(Collections.singletonList(alterScheduleStatusRequest));
        return mesRequest;
    }

    /**
     * 自动刷新排程
     * 如果 当前没有运行中的排程 按照排程开始时间排序 开始一个排程
     */
    @Override
    public BaseResponse autoBeginSchedule() {
        //默认工厂下发工单状态为下发 查询该部分工单
        WorkOrderEntity toBeUpdate = getOne(new QueryWrapper<WorkOrderEntity>()
                .eq("schedule_status", WorkOrderStatusEnum.ISSUED.getCode())
                .eq("schedule_type", 1)
                .orderByAsc("schedule_start_time")
                .last("LIMIT 1")
        );
        if (toBeUpdate == null) {
            return BaseResponse.error("没有可开始的排程");
        }
        //更新工单状态为生产
        return updateScheduleStatus(toBeUpdate, WorkOrderStatusEnum.IN_PRODUCTION);
    }


    @Override
    @Transactional
    public BaseResponse updateScheduleQty() {
        // 获取正在生产的工单
        WorkOrderEntity order = getOne(new QueryWrapper<WorkOrderEntity>()
                .eq("schedule_status", WorkOrderStatusEnum.IN_PRODUCTION.getCode())
                .eq("schedule_type", 1)
        );
        if (order == null) {
            order = getOne(new QueryWrapper<WorkOrderEntity>()
                    .eq("schedule_type", 1)
                    .orderByDesc("schedule_start_time").last("LIMIT 1"));
            log.error("【投产计算】没有找到相应的工单,使用排程:{} 超量生产", order.getScheduleCode());
        }
        Integer finished = order.getScheduleQtyFinished();
        Integer scheduleQty = order.getScheduleQty();
        order.setScheduleQtyFinished(finished + 1);
        // 更新数量
        updateById(order);
        // 检查并更新工单状态
        if (finished + 1 == scheduleQty) {
            updateScheduleStatus(order, WorkOrderStatusEnum.COMPLETED);
            autoBeginSchedule();
        }
        // 更新工单
        return BaseResponse.success();
    }

    @Override
    public WorkOrderEntity getInProcessSchedule() {
        List<WorkOrderEntity> inProcessScheduleList = list(new QueryWrapper<WorkOrderEntity>()
                .eq("schedule_status", WorkOrderStatusEnum.IN_PRODUCTION.getCode())
                //主排程
                .eq("schedule_type", 1)
        );
        if (inProcessScheduleList.size() > 1) {
            log.error("当前产线存在多个生产中的排程！返回第一个");
        } else if (CollectionUtils.isEmpty(inProcessScheduleList)) {
            WorkOrderEntity workOrder = getOne(new QueryWrapper<WorkOrderEntity>()
                    .eq("schedule_type", 1)
                    .orderByDesc("schedule_start_time").last("LIMIT 1"));
            log.error("当前没有生产中的排程,使用排程:{} 超量生产", workOrder.getScheduleCode());
            return workOrder;
        }
        return inProcessScheduleList.get(0);
    }

    @Override
    public WorkOrderEntity getInProcessXpcSchedule() {
        WorkOrderEntity workOrder = getInProcessSchedule();
        return getXpcScheduleByMain(workOrder.getScheduleCode());
    }

    @Override
    public WorkOrderEntity getByScheduleCode(String scheduleCode) {
        return getOne(new QueryWrapper<WorkOrderEntity>().eq("schedule_code", scheduleCode));
    }

    public WorkOrderEntity getXpcScheduleByMain(String mainScheduleCode) {
        return getOne(new QueryWrapper<WorkOrderEntity>().eq("schedule_code", mainScheduleCode + "XPC"));
    }
}
